/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */
package model;

import java.awt.Graphics;
import java.awt.Image;
import java.util.HashMap;
import java.util.Iterator;
import java.util.Map;
import java.util.Map.Entry;

/**
 * De klasse Part is verantwoordelijk voor: zichzelf TEKENNEN zichzelf
 * VERPLAATSEN
 *
 * Part heeft kennis van zijn uiterlijk of hij beweegbaar is en het veld waar
 * hij zich in bevindt
 *
 * Author Misja, Bob.
 */
public abstract class Part {

    protected boolean movable;
    protected Image appereance;
    protected Field currentField;

    /*
     * Lege constuctor deze klasse os abstract 
     * de constructor wordt dus altijd overschreven de de child klasse
     */
    public Part() {
    }

    /*
     * Tekent het Part dit kan een doos, muur speler etc..
     * de methode krijgt mee waarop hij het moet tekennen.
     */
    public void draw(Graphics g) {
        if (this.appereance != null) {
            g.drawImage(
                    appereance,
                    currentField.getxCoordinate(),
                    currentField.getyCoordinate(),
                    null);
        }
    }

    /*
     * recursieve methode werkt nog niet wordt aangewerkt
     */
//    public boolean movePart(String direction) {
//        return movePart(direction, this.currentField);
//    }
//
//    public boolean movePart(String direction, Field currentField) {
//        // movable can move moet nog afgevangen worden
//        Field neighbor = currentField.getNeighbor(direction);
//        if (neighbor != null) {
//            if (neighbor.getPart() == null) {
//                 currentField.setPart(null);
//                neighbor.setPart(this);
//               
//                 setCurrentField(neighbor);
//                return true;
//            } else {
//                if (neighbor.getPart().isMovable()) {
//                    boolean move = movePart(direction, neighbor);
//                    if (move) {
//                         currentField.setPart(null);
//                        neighbor.setPart(this);
//                       
//                        setCurrentField(neighbor);
//                        return true;
//                    }
//                }
//            }
//        }
//        return false;
//    }
    public void movePart(String direction) {

        HashMap<Field, Part> changes = new HashMap<>();
        Field firstField = this.currentField;
        Field activeField;

        // buur veld wordt bepaald en opgeslagen.
        Field neighbor = firstField.getNeighbor(direction);

        // het spel element van het eerste veld wordt tijdelijk bewaard.
        Part currentPart = firstField.getPart();

        // eind conditie wordt bepaald
        boolean endCondition = false;

        /* Hier wordt er gekeken of er wel een buur veld is
         * als er geen buur veld is dan stop de functie. */
        if (neighbor == null) {
            return;
        }

        // Eerste actie wordt altijd opgeslagen.
        changes.put(firstField, null);

        while (endCondition == false) {
            // Hier word gekeken of er een GamePart zit in het buur veld.
            if (neighbor.getPart() == null) {
                // Eind conditie is vervult loop stopt.
                changes.put(neighbor, currentPart);
                endCondition = true;
                break;
            }

            // Hier word gekeken of het onder deel kan worden verplaats;
            if (neighbor.getPart().isMovable()) {
                // Het huidige GamePart wordt in het buur veld opgeslagen.
                changes.put(neighbor, currentPart);
                // Huidige GamePart wordt gevuld met het op object van het buur veld.
                currentPart = neighbor.getPart();
                // Het huidige veld wordt het buur veld.
                activeField = neighbor;
                // Het buur veld wordt de het buur veld van het huidige veld.
                neighbor = activeField.getNeighbor(direction);

                // Als er geen buur veld is dan stop de loop.
                if (neighbor == null) {
                    break;
                }

            } else {
                // Als een onderdeel niet verplaatsbaar is stop de loop.
                break;
            }
        }

        // Kijkt eraan de eindconditie is voldaan zoja dan voert hij het uit.
        if (endCondition) {
            Iterator<Entry<Field, Part>> it = changes.entrySet().iterator();
            while (it.hasNext()) {
                Map.Entry<Field, Part> entry = it.next();
                Field t = entry.getKey();
                Part p = entry.getValue();
                t.setPart(p);
            }
        }
    }

    /**
     * @return the movable
     */
    public boolean isMovable() {
        return movable;
    }

    /**
     * @param movable the movable to set
     */
    public void setMovable(boolean movable) {
        this.movable = movable;
    }

    /**
     * @return the appereance
     */
    public Image getAppereance() {
        return appereance;
    }

    /**
     * @param appereance the appereance to set
     */
    public void setAppereance(Image appereance) {
        this.appereance = appereance;
    }

    /**
     * @return the currentField
     */
    public Field getCurrentField() {
        return currentField;
    }

    /**
     * @param currentField the currentField to set
     */
    public void setCurrentField(Field currentField) {
        this.currentField = currentField;
        if (currentField != null) {
            if (currentField.getPart() == null) {
                currentField.setPart(this);
            } else if (!this.currentField.getPart().equals(this)) {
                this.currentField.setPart(this);
            }
        }
    }
}
